//
// Book:      OpenGL(R) ES 2.0 Programming Guide
// Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
// ISBN-10:   0321502795
// ISBN-13:   9780321502797
// Publisher: Addison-Wesley Professional
// URLs:      http://safari.informit.com/9780321563835
//            http://www.opengles-book.com
//

// Hello_Triangle.c
//
//    This is a simple example that draws a single triangle with
//    a minimal vertex/fragment shader.  The purpose of this 
//    example is to demonstrate the basic concepts of 
//    OpenGL ES 2.0 rendering.
#include <stdlib.h>
#include "esUtil.h"
#include "ShaderProcessing.h"
typedef struct
{
   // Handle to a program object
   GLuint programObject;

} UserData;

///
// Create a shader object, load the shader source, and
// compile the shader.
//
GLuint LoadShader ( GLenum type, const char *shaderSrc )
{
   GLuint shader;
   GLint compiled;
   
   // Create the shader object
   shader = glCreateShader ( type );

   if ( shader == 0 )
   	return 0;

   // Load the shader source
   glShaderSource ( shader, 1, &shaderSrc, NULL );
   
   // Compile the shader
   glCompileShader ( shader );

   // Check the compile status
   glGetShaderiv ( shader, GL_COMPILE_STATUS, &compiled );

   if ( !compiled ) 
   {
      GLint infoLen = 0;

      glGetShaderiv ( shader, GL_INFO_LOG_LENGTH, &infoLen );
      
      if ( infoLen > 1 )
      {
         char* infoLog = new char[infoLen];

         glGetShaderInfoLog ( shader, infoLen, NULL, infoLog );
         esLogMessage ( "Error compiling shader:\n%s\n", infoLog );            
         
         free ( infoLog );
      }

      glDeleteShader ( shader );
      return 0;
   }

   return shader;

}

//char* GetShaderContent(char* shadername)
//{
//	ifstream in(shadername);
//	string xxx ="", result="";
//	while(getline(in, xxx)) 
//	{
//		result = result + "" + xxx + "\n"; 
//	}
//	char * nnn = new char[result.size() + 1];
//	std::copy(result.begin(), result.end(), nnn);
//	nnn[result.size()] = '\0';
//	return nnn;
//}

///
// Initialize the shader and program object
//
int Init ( ESContext *esContext )
{
   UserData *userData = (UserData *) esContext->userData;
   /*char* vShaderStr  =  
      "attribute vec4 vPosition;    \n"	  
	  "attribute vec4 aColor;		\n"
	  "varying vec4 vColor;			\n"
      "void main()                  \n"
      "{                            \n"
      "   gl_Position = vPosition;  \n"
	  "   vColor = aColor;			\n"
	  	
	   "}                            \n";
   
   
   char* fShaderStr =  
      "precision mediump float;						\n"
	  "varying vec4 vColor;							\n"					
      "void main()                                  \n"
      "{                                            \n"
      "  gl_FragColor = vColor;						\n"
      "}                                            \n";*/
   char* vShaderStr = NULL;
   char* fShaderStr = NULL;
   vShaderStr = GetShaderContent("C:/triangle.vs_");
   fShaderStr = GetShaderContent("triangle.fs");
   GLuint vertexShader;
   GLuint fragmentShader;
   GLuint programObject;
   GLint linked;

   // Load the vertex/fragment shaders
   vertexShader = LoadShader ( GL_VERTEX_SHADER, vShaderStr );
   fragmentShader = LoadShader ( GL_FRAGMENT_SHADER, fShaderStr );

   // Create the program object
   programObject = glCreateProgram ( );
   
   if ( programObject == 0 )
      return 0;

   glAttachShader ( programObject, vertexShader );
   glAttachShader ( programObject, fragmentShader );

   // Bind vPosition to attribute 0   
   glBindAttribLocation ( programObject, 0, "vPosition" );
	// Bind vColor to attribute 1
   glBindAttribLocation ( programObject, 1, "aColor" );
   // Link the program
   glLinkProgram ( programObject );

   // Check the link status
   glGetProgramiv ( programObject, GL_LINK_STATUS, &linked );

   if ( !linked ) 
   {
      GLint infoLen = 0;

      glGetProgramiv ( programObject, GL_INFO_LOG_LENGTH, &infoLen );
      
      if ( infoLen > 1 )
      {
         char* infoLog = new char[infoLen];

         glGetProgramInfoLog ( programObject, infoLen, NULL, infoLog );
         esLogMessage ( "Error linking program:\n%s\n", infoLog );            
         
         free ( infoLog );
      }

      glDeleteProgram ( programObject );
      return FALSE;
   }

   // Store the program object
   userData->programObject = programObject;

   glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
   return TRUE;
}

///
// Draw a triangle using the shader pair created in Init()
//
void Draw ( ESContext *esContext )
{
	glEnable(GL_CULL_FACE);
	glDisable(GL_CULL_FACE);
   UserData *userData =  (UserData *) esContext->userData;
   /*GLfloat vVertices[] = {  0.0f,  0.5f, 0.0f,							 
                           -0.5f, -0.5f, 0.0f,
						   0.5f, -0.5f, 0.0f,

                           };*/
   GLfloat vVertices[] = {  
							
							-0.5f,  0.5f, 0.0f,							 
                           -0.5f, -0.5f, 0.0f,
						   0.5f, -0.5f, 0.0f,
						   0.5f, 0.5f, 0.0f,
							
                           };
   GLfloat vColors[] = { 1.0f, 0.0f, 0.0f, 0.0f,
						 0.0f, 1.0f, 0.0f, 0.0f,
						 0.0f, 0.0f, 1.0f, 0.0f, 
						 1.0f, 0.0f, 1.0f, 0.0f	
						};
      
   // Set the viewport
   glViewport ( 0, 0, esContext->width, esContext->height );
   
   // Clear the color buffer
   glClear ( GL_COLOR_BUFFER_BIT );

   // Use the program object
   glUseProgram ( userData->programObject );

   // Load the vertex data
   glVertexAttribPointer ( 0, 3, GL_FLOAT, GL_FALSE, 0, vVertices );
   glEnableVertexAttribArray ( 0 );

   // Load the color data
   glVertexAttribPointer (1, 4, GL_FLOAT, GL_FALSE, 0, vColors );
   glEnableVertexAttribArray ( 1 );

   glDrawArrays ( GL_TRIANGLE_FAN, 0, 4 );

   eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );
}


int main ( int argc, char *argv[] )
{
   ESContext esContext;
   UserData  userData;

   esInitContext ( &esContext );
   esContext.userData = &userData;

   esCreateWindow ( &esContext, "Hello Triangle", 640, 640, ES_WINDOW_RGB );
   
   if ( !Init ( &esContext ) )
      return 0;

   esRegisterDrawFunc ( &esContext, Draw );
   
   esMainLoop ( &esContext );
}
